/*
 * @brief:
 * @Author: TzzzT
 * @Date: 2022-09-24 13:46:12
 * @LastEditTime: 2023-05-20 01:09:31
 * @LastEditors: TzzzT
 */
#include "esp_system.h"
#include "esp_log.h"

#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"

#include "string.h"
#include "find_string.h"

#include "RCS_uart.h"
#include "bc260.h"
#include "RCS_master.h"

static const char *BC_TAG = "BC_TAG";

///////////////////BC260///////////////////
bc260_t bc260;

void bc260_receive_message(rx_pbuf_t *p)
{
  switch (bc260.stage)
  {
  case INIT_BC260:
  case FIND_NET_BC260:
  case CHECK_NET_BC260:
  case OPENING_SERVR_BC260:
  {
    if (sunday(p->databuf, "+QIOPEN:") >= 0 || sunday(p->databuf, "+QIURC") >= 0)
    {
      ESP_LOGI("bc_rec", "send to inform queue");
      xQueueSend(bc260.inform_queue, &p, portMAX_DELAY);
    }
    else
    {
      // ESP_LOGE("bc_rec", "send p: %p to resp queue", p);
      xQueueSend(bc260.resp_queue, &p, portMAX_DELAY);
    }
    break;
  }
  case CONNECTTED_BC260:
  {
    if (sunday(p->databuf, "+QIOPEN:") >= 0 || sunday(p->databuf, "+QIURC") >= 0)
    {
      ESP_LOGI("bc_rec", "send to inform queue");
      xQueueSend(bc260.inform_queue, &p, portMAX_DELAY);
    }
    else
    {
      uart_pbuf_free(p);
    }

    break;
  }
  default:
    break;
  }
}

// uint8_t bc_check_something(uint8_t idx);
void set_baudrate(uint32_t baud);
// uint8_t bc_wake_check(void);
uint8_t bc_test_baudrate(void);
uint8_t bc_get_cpin_ready(void);
// uint8_t _bc_send_cpin_ready(void);
uint8_t bc_show_off_command(void);
uint8_t bc_stop_deepsleep_command(void);
uint8_t bc_cgatt_check(void);
uint8_t bc_get_ip(void);
uint8_t bc_set_data_format(void);

uint8_t bc_open_socket(void);
uint8_t bc_close_socket(void);
uint8_t bc_wait_open_result(void);

uint8_t receive_bc_inform_message(rx_pbuf_t *dummy_p);

uint8_t bc_set_cedrxs(void);
uint8_t bc_set_cpsms(void);
uint8_t bc_qcsearfecn(void);
uint8_t bc_cfun(uint8_t mode);
uint8_t bc_rst(void);

#define CFUN_TRY_NUM 3
static void bc_260_state_machine_task(void *arg)
{
  uint8_t cpin_try_num = 3;
  uint8_t cfun_try_num = CFUN_TRY_NUM;
  while (1)
  {
    switch (bc260.stage)
    {
    case INIT_BC260:
    {
      bc_test_baudrate();
      vTaskDelay(pdMS_TO_TICKS(1000));
      bc_show_off_command();
      vTaskDelay(pdMS_TO_TICKS(1000));
      bc_stop_deepsleep_command();
      vTaskDelay(pdMS_TO_TICKS(1000));
      bc_set_cedrxs();
      vTaskDelay(pdMS_TO_TICKS(1000));
      bc_set_cpsms();
      vTaskDelay(pdMS_TO_TICKS(1000));
      bc260.stage = CHECK_NET_BC260;
      break;
    }
    case FIND_NET_BC260:
    {
      cfun_try_num--;
      ESP_LOGE(BC_TAG, "cfun_try_num:%d.", cfun_try_num);
      if (cfun_try_num <= 0)
      {
        cfun_try_num = CFUN_TRY_NUM;
        bc_rst();
        bc260.stage = INIT_BC260;
        vTaskDelay(pdMS_TO_TICKS(3000));
      }
      else
      {
        bc_cfun(0);
        vTaskDelay(pdMS_TO_TICKS(1000));
        bc_qcsearfecn();
        vTaskDelay(pdMS_TO_TICKS(2000));
        uint8_t res = bc_cfun(1);
        vTaskDelay(pdMS_TO_TICKS(3000));
        if (res == 1)
        {
          cfun_try_num = CFUN_TRY_NUM;
          bc_rst();
          bc260.stage = INIT_BC260;
          vTaskDelay(pdMS_TO_TICKS(3000));
        }
        else
        {
          bc260.stage = CHECK_NET_BC260;
        }
      }

      break;
    }
    case CHECK_NET_BC260:
    {
      if (bc_get_cpin_ready() == 1)
      {
        if (cpin_try_num > 0)
        {
          cpin_try_num--;
        }
        else
        {
          cpin_try_num = 3;
          bc260.stage = FIND_NET_BC260;
        }
        vTaskDelay(pdMS_TO_TICKS(3000));
      }
      else
      {
        cpin_try_num = 3;
        vTaskDelay(pdMS_TO_TICKS(1000));
        if (bc_cgatt_check() == 0)
        {
          vTaskDelay(pdMS_TO_TICKS(1000));
          bc_get_ip();
          vTaskDelay(pdMS_TO_TICKS(1000));
          bc_set_data_format();
          vTaskDelay(pdMS_TO_TICKS(1000));
          bc260.stage = OPENING_SERVR_BC260;
        }
        else
        {
          vTaskDelay(pdMS_TO_TICKS(1000));
          if (bc260.rst_flag == 0)
          {
            bc260.stage = FIND_NET_BC260;
            bc260.rst_flag = 1;
          }
          else
          {
            bc260.rst_flag = 0;
            bc_rst();
            bc260.stage = INIT_BC260;
            vTaskDelay(pdMS_TO_TICKS(1000));
          }
        }
      }

      break;
    }
    case OPENING_SERVR_BC260:
    {
      switch (bc260.open_state)
      {
      case SEND_OPEN:
      {
        uint8_t ret = bc_open_socket();
        vTaskDelay(pdMS_TO_TICKS(1000));
        if (ret == 1)
        {
          bc260.open_state = CLOSE_OPEN;
        }
        else
        {
          bc260.open_state = WAIT_OPEN_RESULT;
        }
        break;
      }
      case CLOSE_OPEN:
      {
        bc_close_socket();
        vTaskDelay(pdMS_TO_TICKS(1000));
        bc260.open_state = SEND_OPEN;
        break;
      }
      case WAIT_OPEN_RESULT:
      {
        uint8_t ret = bc_wait_open_result();
        vTaskDelay(pdMS_TO_TICKS(1000));
        if (ret == 0)
        {
          bc260.open_state = SEND_OPEN;
          bc260.stage = CONNECTTED_BC260;
          bc260.reopen_flag = 0;
          bc260.wait70s_flag = 0;
        }
        else
        {
          if (bc260.reopen_flag == 0)
          {
            bc260.reopen_flag = 1;
            bc260.open_state = SEND_OPEN;
          }
          // else if (bc260.wait70s_flag == 0)
          // {
          //   bc260.wait70s_flag = 1;
          //   vTaskDelay(pdMS_TO_TICKS(70000));
          //   bc260.open_state = SEND_OPEN;
          // }
          else
          {
            bc260.wait70s_flag = 0;
            bc260.reopen_flag = 0;
            bc260.stage = FIND_NET_BC260;
          }
        }
        break;
      }
      default:
        break;
      }
      break;
    }
    case CONNECTTED_BC260:
    {
      BaseType_t xStatus;
      rx_pbuf_t *dummy_p;
      xStatus = xQueueReceive(bc260.inform_queue, &dummy_p, portMAX_DELAY);
      uint8_t is_net_close = receive_bc_inform_message(dummy_p);
      uart_pbuf_free(dummy_p);
      if (is_net_close)
      {
        bc260.stage = OPENING_SERVR_BC260;
        if (bc260.net_down_cb)
        {
          bc260.net_down_cb(0);
        }
      }
      break;
    }
    default:
      break;
    }
  }
}

void bc260_init(inform_cb_t _inform_cb, net_up_cb_t _up_cb, net_down_cb_t _down_cb)
{
  bc260.stage = INIT_BC260;
  bc260.open_state = SEND_OPEN;
  bc260.current_baud = DEFAULT_BAUDRATE;
  bc260.resp_queue = xQueueCreate(BC260_INFORM_Q_LENGTH, sizeof(rx_pbuf_t *));
  bc260.inform_queue = xQueueCreate(BC260_RESP_Q_LENGTH, sizeof(rx_pbuf_t *));
  bc260.inform_cb = _inform_cb;
  bc260.net_up_cb = _up_cb;
  bc260.net_down_cb = _down_cb;
  init_uart(bc260_receive_message);
  set_baudrate(TARGET_BAUDRATE);
  xTaskCreate(bc_260_state_machine_task, "bc_state_machine", 1024 * 25, NULL, 13, NULL);
  return;
}

void set_baudrate(uint32_t baud)
{
  esp_err_t err = uart_set_baud(baud);

  if (err == ESP_OK)
  {
    bc260.current_baud = baud;
  }
  else
  {
    printf("set_baudrate failed, err(%s)\n", esp_err_to_name(err));
  }
}

void clean_queue(QueueHandle_t xQueue)
{
  // xQueueReset(xQueue);
}

uint8_t bc_test_baudrate(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char set_baud_command[] = "AT+IPR=115200\r\n";
  char wake_command[] = "AT\r\n";

  uint8_t quit_flag = 1;
  while (quit_flag)
  {
    ESP_LOGE(BC_TAG, "send %s", wake_command);
    uart_send_data(wake_command, strlen(wake_command));
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(2000));
    if (pdPASS == xStatus)
    {
      if (sunday(dummy_p->databuf, "OK") >= 0)
      {
        ret = 0;
      }
      uart_pbuf_free(dummy_p);
    }
    else
    {
      // 没有收到回复，第一次上电，需要设置波特率是9600.
      quit_flag = 0;
    }

    if (ret == 0)
    {
      return ret;
    }
  }
  // 认为模块波特率为9600.修改串口波特率
  set_baudrate(DEFAULT_BAUDRATE);
  quit_flag = 1;
  while (quit_flag)
  {
    ESP_LOGE(BC_TAG, "send %s", set_baud_command);
    uart_send_data(set_baud_command, strlen(set_baud_command));
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(2000));
    if (pdPASS == xStatus)
    {
      if (sunday(dummy_p->databuf, "OK") >= 0)
      {
        quit_flag = 0;
        ESP_LOGI(BC_TAG, "set 115200 baudrate");
        set_baudrate(TARGET_BAUDRATE);
      }
      uart_pbuf_free(dummy_p);
    }
  }

  quit_flag = 1;
  while (quit_flag)
  {
    ESP_LOGE(BC_TAG, "send %s", set_baud_command);
    uart_send_data(set_baud_command, strlen(set_baud_command));
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(2000));
    if (pdPASS == xStatus)
    {
      if (sunday(dummy_p->databuf, "OK") >= 0)
      {
        quit_flag = 0;
        ESP_LOGI(BC_TAG, "confirm 115200 baudrate");
      }
      uart_pbuf_free(dummy_p);
    }
  }

  return ret;
}

uint8_t bc_show_off_command(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  uint8_t quit_flag = 1;
  char showoff_command[] = "ATE0\r\n";

  ESP_LOGE(BC_TAG, "send %s", showoff_command);
  uart_send_data(showoff_command, strlen(showoff_command));
  quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_stop_deepsleep_command(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char stopsleep_command[] = "AT+QSCLK=0\r\n";
  ESP_LOGE(BC_TAG, "send %s", stopsleep_command);
  uart_send_data(stopsleep_command, strlen(stopsleep_command));
  uint8_t quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_check_something(uint8_t idx)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char command[6][20] = {
      "AT+CSQ\r\n",
      "AT+CESQ\r\n",
      "AT+CEREG?\r\n",
      "AT+CPIN?\r\n",
      "AT+CSCON?\r\n",
      "AT+QENG=0\r\n"};
  char resp_command[6][20] = {
      "+CSQ",
      "+CESQ",
      "+CEREG",
      "+CPIN",
      "+CSCON",
      "+QENG"};
  clean_queue(bc260.resp_queue);
  while (ret)
  {
    ESP_LOGE(BC_TAG, "send %s", command[idx]);
    uart_send_data(command[idx], strlen(command[idx]));
    uint8_t quit_flag = 1;
    while (quit_flag)
    {
      xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, portMAX_DELAY);
      esp_log_buffer_char("RESP", dummy_p->databuf, dummy_p->datasize);
      int16_t result_success = sunday(dummy_p->databuf, resp_command[idx]);
      ESP_LOGI("RESP", "result_success:%d", result_success);
      uart_pbuf_free(dummy_p);
      if (result_success >= 0)
      {
        ret = 0;
        quit_flag = 0;
      }
      else
      {
        ESP_LOGI(BC_TAG, "get no use");
      }
    }
    quit_flag = 1;
    while (quit_flag)
    {
      // 还要读一个OK
      xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, portMAX_DELAY);
      int16_t result_success = sunday(dummy_p->databuf, "OK");
      int16_t result_failed = sunday(dummy_p->databuf, "ERROR");
      uart_pbuf_free(dummy_p);
      if (result_success >= 0 || result_failed >= 0)
      {
        quit_flag = 0;
      }
      else
      {
        ESP_LOGI(BC_TAG, "get no use, wait ok");
      }
    }
  }
  return ret;
}

uint8_t bc_show_something(uint8_t idx)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char command[6][20] = {
      "AT+CSQ\r\n",
      "AT+CESQ\r\n",
      "AT+CEREG?\r\n",
      "AT+CPIN?\r\n",
      "AT+CSCON?\r\n",
      "AT+QENG=0\r\n"};
  char resp_command[6][20] = {
      "+CSQ\r\n",
      "+CESQ\r\n",
      "+CEREG?\r\n",
      "+CPIN?\r\n",
      "+CSCON?\r\n",
      "+QENG=0\r\n"};
  ESP_LOGE(BC_TAG, "send %s", command[idx]);
  uart_send_data(command[idx], strlen(command[idx]));
  return ret;
}

uint8_t bc_get_cpin_ready(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char cpin_ready_command[] = "AT+CPIN?\r\n";
  uint8_t quit_flag = 1;

  ESP_LOGI(BC_TAG, "send %s", cpin_ready_command);
  uart_send_data(cpin_ready_command, strlen(cpin_ready_command));
  quit_flag = 1;
  int16_t ret_f = -1;
  int16_t ret_s = -1;
  int16_t result_success = -1;
  int16_t result_failed = -1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    if (result_success == -1)
    {
      result_success = sunday(dummy_p->databuf, "+CPIN: READY");
    }
    if (result_failed == -1)
    {
      result_failed = sunday(dummy_p->databuf, "+CPIN: NOT READY");
    }
    if (ret_f == -1)
    {
      ret_f = sunday(dummy_p->databuf, "ERROR");
    }
    if (ret_s == -1)
    {
      ret_s = sunday(dummy_p->databuf, "OK");
    }
    uart_pbuf_free(dummy_p);

    if (ret_f >= 0)
    {
      return ret;
    }

    if (ret_s >= 0 && result_success >= 0)
    {
      ret = 0;
      return ret;
    }

    if (ret_s >= 0 && result_failed >= 0)
    {
      ret = 1;
      return ret;
    }
  }
  return ret;
}

enum
{
  GET_CGATT,
  SET_CGATT,
};

uint8_t bc_cgatt_check(void)
{
  ESP_LOGI(BC_TAG, "bc_config_cgatt");
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  uint8_t error_count = 3;
  char cgatt_check_command[] = "AT+CGATT?\r\n";
  uint8_t stage = GET_CGATT;

  uint8_t try_count = 10;
  uint8_t quit_flag = 1;
  uint8_t get_result = 0;
  while (try_count > 0)
  {
    try_count--;
    vTaskDelay(pdMS_TO_TICKS(3000));
    ESP_LOGE(BC_TAG, "retry:%d. send %s", try_count, cgatt_check_command);
    uart_send_data(cgatt_check_command, strlen(cgatt_check_command));
    quit_flag = 1;
    while (quit_flag > 0)
    {
      xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(70000));
      if (xStatus != pdPASS)
      {
        return 1;
      }
      // esp_log_buffer_char("AA", dummy_p->databuf, dummy_p->datasize);
      int16_t result_success = sunday(dummy_p->databuf, "+CGATT: 1");
      int16_t result_failed = sunday(dummy_p->databuf, "+CGATT: 0");
      uart_pbuf_free(dummy_p);
      if (result_success >= 0)
      {
        ESP_LOGE(BC_TAG, "get +CGATT: 1, wait OK");
        ret = 0;
        get_result = 1;
        quit_flag = 0;
      }
      else if (result_failed >= 0)
      {
        ESP_LOGE(BC_TAG, "get +CGATT: 0, wait OK");
        quit_flag = 0;
      }
      else
      {
        // ESP_LOGI(BC_TAG, "get no use length: %d", dummy_p->datasize);
        // esp_log_buffer_char("A", dummy_p->databuf, dummy_p->datasize);
      }
    }
    quit_flag = 1;
    while (quit_flag)
    {
      // 还要读一个OK
      xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(10000));
      if (xStatus != pdPASS)
      {
        return 1;
      }
      // esp_log_buffer_char("A", dummy_p->databuf, dummy_p->datasize);
      int16_t result_success = sunday(dummy_p->databuf, "OK");
      int16_t result_failed = sunday(dummy_p->databuf, "ERROR");
      uart_pbuf_free(dummy_p);
      if (result_success >= 0)
      {
        ESP_LOGE(BC_TAG, "get OK");
        quit_flag = 0;
      }
      else if (result_failed >= 0)
      {
        ESP_LOGE(BC_TAG, "get ERROR");
        quit_flag = 0;
      }
      else
      {
        // ESP_LOGI(BC_TAG, "get no use: %d ", dummy_p->datasize);
        // esp_log_buffer_char("A", dummy_p->databuf, dummy_p->datasize);
      }
    }
    if (get_result)
    {
      return ret;
    }
  }
  return ret;
}

uint8_t bc_get_ip(void)
{
  clean_queue(bc260.resp_queue);
  ESP_LOGI(BC_TAG, "bc_get_ip");
  char find_net_command[] = "AT+CGPADDR=0\r\n";
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  while (ret)
  {
    ESP_LOGE(BC_TAG, "send %s", find_net_command);
    uart_send_data(find_net_command, strlen(find_net_command));
    uint8_t quit_flag = 1;
    while (quit_flag)
    {
      xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
      if (xStatus != pdPASS)
      {
        return 1;
      }
      if (sunday(dummy_p->databuf, "+CGPADDR: 0,") >= 0)
      {
        ret = 0;
        quit_flag = 0;
        ESP_LOGE(BC_TAG, "find_net success");
      }
      uart_pbuf_free(dummy_p);
    }
    quit_flag = 1;
    while (quit_flag)
    {
      xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
      if (xStatus != pdPASS)
      {
        return 1;
      }
      if (sunday(dummy_p->databuf, "OK") >= 0)
      {
        quit_flag = 0;
        uart_pbuf_free(dummy_p);
      }
    }
  }
  return ret;
}

uint8_t bc_set_data_format(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char setformat_command[] = "AT+QICFG=\"dataformat\",0,1\r\n";
  ESP_LOGE(BC_TAG, "send %s", setformat_command);
  uart_send_data(setformat_command, strlen(setformat_command));
  uint8_t quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_set_cedrxs(void)
{
  clean_queue(bc260.resp_queue);
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  uint8_t quit_flag = 1;
  char set_cedrxs_command[] = "AT+CEDRXS=0\r\n";
  ESP_LOGE(BC_TAG, "send %s", set_cedrxs_command);
  uart_send_data(set_cedrxs_command, strlen(set_cedrxs_command));
  quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_set_cpsms(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  uint8_t quit_flag = 1;
  char set_cpsms[] = "AT+CPSMS=0\r\n";

  ESP_LOGE(BC_TAG, "send %s", set_cpsms);
  uart_send_data(set_cpsms, strlen(set_cpsms));
  quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_qcsearfecn(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  uint8_t quit_flag = 1;
  char qcsearfecn[] = "AT+QCSEARFCN\r\n";

  ESP_LOGE(BC_TAG, "send %s", qcsearfecn);
  uart_send_data(qcsearfecn, strlen(qcsearfecn));
  quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_cfun(uint8_t mode)
{
  clean_queue(bc260.resp_queue);
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char send_cfun0[] = "AT+CFUN=0\r\n";
  char send_cfun1[] = "AT+CFUN=1\r\n";

  ESP_LOGI(BC_TAG, "send cfun %d", mode);
  if (mode == 1)
  {
    uart_send_data(send_cfun1, strlen(send_cfun1));
  }
  else if (mode == 0)
  {
    uart_send_data(send_cfun0, strlen(send_cfun0));
  }

  uint8_t quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(25000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    if (sunday(dummy_p->databuf, "OK") >= 0)
    {
      quit_flag = 0;
      ret = 0;
    }
    else if (sunday(dummy_p->databuf, "ERROR") >= 0)
    {
      quit_flag = 0;
      ret = 1;
    }
    uart_pbuf_free(dummy_p);
  }
  return ret;
}

uint8_t bc_rst(void)
{
  clean_queue(bc260.resp_queue);
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char send_rst[] = "AT+QRST=1\r\n";
  uint8_t quit_flag = 1;
  ESP_LOGE(BC_TAG, "send %s", send_rst);
  uart_send_data(send_rst, strlen(send_rst));
  quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    int res_s = sunday(dummy_p->databuf, "OK");
    int res_f = sunday(dummy_p->databuf, "ERROR");
    uart_pbuf_free(dummy_p);
    if (res_s >= 0)
    {
      ret = 0;
      quit_flag = 0;
    }
    if (res_f >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
  }
  return ret;
}

uint8_t bc_open_socket(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  // char open_socket_command[] = "AT+QIOPEN=0,0,\"TCP\",\"4gf1776451.wicp.vip\",21686\r\n";
  // char open_socket_command[] = "AT+QIOPEN=0,0,\"TCP\",\"4gf1776451.wicp.vip\",51983\r\n";
  // char open_socket_command[] = "AT+QIOPEN=0,0,\"TCP\",\"4gf1776451.wicp.vip\",56066\r\n";
  char open_socket_command[] = "AT+QIOPEN=0,0,\"TCP\",\"hcsocket.wenbentec.com\",30091,0,1\r\n";

  ESP_LOGE(BC_TAG, "send %s", open_socket_command);
  uart_send_data(open_socket_command, strlen(open_socket_command));
  uint8_t quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    if (sunday(dummy_p->databuf, "OK") >= 0)
    {
      ESP_LOGE(BC_TAG, "OPEN SOCKET SUCCESS");
      quit_flag = 0;
      ret = 0;
    }
    else if (sunday(dummy_p->databuf, "ERROR") >= 0)
    {
      ESP_LOGE(BC_TAG, "OPEN SOCKET FAILED");
      quit_flag = 0;
      ret = 1;
    }
    uart_pbuf_free(dummy_p);
  }
  return ret;
}

uint8_t bc_close_socket(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  char close_socket_command[] = "AT+QICLOSE=0\r\n";
  ESP_LOGE(BC_TAG, "send %s", close_socket_command);
  uint8_t quit_flag = 1;
  uart_send_data(close_socket_command, strlen(close_socket_command));
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    char _ok[3] = "OK";
    if (memcmp(dummy_p->databuf, _ok, 2) == 0)
    {
      quit_flag = 0;
    }
    uart_pbuf_free(dummy_p);
  }
  quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.resp_queue, &dummy_p, pdMS_TO_TICKS(5000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    if (sunday(dummy_p->databuf, "CLOSE OK") >= 0)
    {
      quit_flag = 0;
    }
    uart_pbuf_free(dummy_p);
  }
  return ret;
}

uint8_t bc_wait_open_result(void)
{
  uint8_t ret = 1;
  BaseType_t xStatus;
  rx_pbuf_t *dummy_p;
  ESP_LOGE(BC_TAG, "wait OPEN RESULT");
  uint8_t quit_flag = 1;
  while (quit_flag)
  {
    xStatus = xQueueReceive(bc260.inform_queue, &dummy_p, pdMS_TO_TICKS(60000));
    if (xStatus != pdPASS)
    {
      return 1;
    }
    if (sunday(dummy_p->databuf, "+QIOPEN: 0,0") >= 0)
    {
      // bc260.stage = CONNECTTED_BC260;
      ret = 0;
      quit_flag = 0;
      if (bc260.net_up_cb)
      {
        bc260.net_up_cb(1);
      }
    }
    else if (sunday(dummy_p->databuf, "+QIOPEN: 0,5") >= 0)
    {
      ret = 1;
      quit_flag = 0;
    }
    uart_pbuf_free(dummy_p);
  }
  return ret;
}

int16_t get_recv_len(char *package, uint8_t *len_len);

static bool change_data_char_to_bytes(char *package, uint8_t *dest_data, uint16_t raw_len)
{
  bool res = true;
  if (raw_len % 2 != 0)
  {
    ESP_LOGE(BC_TAG, "raw_len/2 != 0: %d", raw_len);
  }
  int i = 0, j = 0;
  for (i = 0; i < raw_len; i += 2)
  {
    if (((package[i] >= '0' && package[i] <= '9') || (package[i] >= 'a' && package[i] <= 'f') ||
         (package[i] >= 'A' && package[i] <= 'F')) &&
        ((package[i + 1] >= '0' && package[i + 1] <= '9') || (package[i + 1] >= 'a' && package[i + 1] <= 'f') ||
         (package[i + 1] >= 'A' && package[i + 1] <= 'F')))
    {
      char dummy[3] = {0};
      char *p;
      dummy[0] = package[i];
      dummy[1] = package[i + 1];
      dest_data[j++] = strtol(dummy, &p, 16);
    }
    else
    {
      ESP_LOGE(BC_TAG, "error i:%d --- %02x %02x", i, package[i], package[i + 1]);
      res = false;
      break;
    }
  }
  return res;
}

// in net task
uint8_t receive_bc_inform_message(rx_pbuf_t *dummy_p)
{
  uint8_t ret = 0;
  // esp_log_buffer_char("inform", dummy_p->databuf, dummy_p->datasize);
  int16_t idx = sunday(dummy_p->databuf, "recv");
  if (idx >= 0)
  {
    //+QIURC:"recv",0,105,"$start@["
    // ESP_LOGE("raw", "get %d bytes from queue", dummy_p->datasize);
    char *_p = dummy_p->databuf;
    // esp_log_buffer_char("raw", _p, dummy_p->datasize);
    int j = 0;
    char _tag[2] = ",";
    for (j = 0; j < 2; j++)
    {
      idx = sunday(_p, _tag);
      // ESP_LOGI("extract", ",, idx: %d", idx);
      _p = _p + idx + 1;
    }
    // get length
    uint8_t len_len = 0;
    int16_t server_len = get_recv_len(_p, &len_len);
    if (server_len == -1)
    {
      ESP_LOGI("EXT", "get server length error");
    }
    // ESP_LOGE("raw", "server_len: %d", server_len);
    _p += len_len;
    _p += 2; // ,"
    uint8_t *server_bytes_data = calloc(1, (uint16_t)server_len);
    // 实际是2倍serverlen +QIURC: "recv",0,10,"31323334353637383930"
    change_data_char_to_bytes(_p, server_bytes_data, server_len * 2);
    // esp_log_buffer_char("X", server_bytes_data + 8, server_len - 8);
    if (bc260.inform_cb != NULL)
    {
      bc260.inform_cb(server_bytes_data, server_len);
    }
    free(server_bytes_data);
  }
  else if (sunday(dummy_p->databuf, "closed") >= 0)
  {
    ret = 1;
  }
  return ret;
}

int16_t get_recv_socket(char *package)
{
  return sunday(package, "0");
}

int16_t get_recv_len(char *package, uint8_t *len_len)
{
  char len_str[5] = {0};
  uint16_t idx = 0;
  while (package[idx] != ',')
  {
    len_str[idx] = package[idx];
    idx++;
  }
  *len_len = idx;
  return atoi(len_str);
}

uint8_t get_len_size(size_t len)
{
  uint8_t size = 0;
  int i = 1;
  while (len / i != 0)
  {
    i *= 10;
    size++;
  }
  return size;
}

extern rcs_mast_system_t rcsSystem;
//"AT+QISEND=0,10,"1234567890"\r\n"
// 12 + len_size + 2 + whole_package + 3 + 1(结束符)
#define DATA_FORMAT_LEN (18)
void bc_send_package_to_server(char *package, size_t raw_len)
{
  if (raw_len == 0)
  {
    return;
  }
  if (!rcsSystem.net.is_connected)
  {
    ESP_LOGE(BC_TAG, "don't open server");
    return;
  }
  size_t whole_package_len = raw_len + 5;
  uint8_t len_size = get_len_size(whole_package_len);
  size_t whole_data_len = DATA_FORMAT_LEN + len_size + whole_package_len;
  char *bc_send_data = calloc(1, whole_data_len);
  sprintf(bc_send_data, "AT+QISEND=0,%d,\"%s$end@\"\r\n", whole_package_len, package);
  uart_send_data(bc_send_data, whole_data_len);
  esp_log_buffer_char("send", bc_send_data, whole_data_len);
  free(bc_send_data);
  return;
}
